#ifndef MODULES_MAP_HDMAP_ADAPTER_ODR_PARSER_CONVERT_TO_HDMAP_H_
#define MODULES_MAP_HDMAP_ADAPTER_ODR_PARSER_CONVERT_TO_HDMAP_H_

#include "modules/map/hdmap/adapter/odr_parser/data_define.h"

#include "modules/map/proto/map.pb.h"
#include "modules/map/hdmap/adapter/xml_parser/common_define.h"
#include "modules/map/hdmap/adapter/xml_parser/status.h"

#include "modules/map/hdmap/adapter/odr_parser/roadengine_api.h"

namespace apollo {
namespace hdmap {
namespace adapter {

class OdrToHdmapConverter {
public:
  typedef std::map<std::int64_t, rg::RoadGeometry::Ptr> RoadGeometryMap;
  typedef std::map<int, rg::LaneDivRefLine> SectionLaneDivLines;

  static void ConvertRoads(const OdrMap& map_, std::vector<RoadInternal>& roads, 
                           RoadGeometryMap& roadGeometries, bool reverseXAxis);

  static void ConvertJunctions(const OdrMap& map_, 
                                  const std::vector<RoadInternal>& roads,
                                  std::vector<JunctionInternal>& junctions);

private:
  static void ConvertObjects(const Road &road, RoadInternal& road_internal,
                             const rg::RoadGeometry::Ptr roadGeometry);
  static void ConvertSignals(const Road &road, RoadInternal& road_internal);
  static void ConvertTrafficLight(const Road &road,
                                     const RoadSignal& road_signal,
                                     RoadInternal& road_internal);
  static void ToPbLightType(const std::string& layout,
                                        PbSignalType& signal_type);                                 
  static void ToPbSubSignalType(const std::string& xml_type,
                                           PbSubSignalType& sub_signal_type);
  static void ConvertCrossWalk(const Road &road,
                               const RoadObject& road_obj,
                               RoadInternal& road_internal,
                               const rg::RoadGeometry::Ptr roadGeometry);
  static void ConvertStopLine(const Road &road, 
                              const RoadObject& road_obj,
                              RoadInternal& road_internal,
                              const rg::RoadGeometry::Ptr /*roadGeometry*/);

  static void ConvertLaneSections(const Road &road,
                std::vector<RoadSectionInternal>* sections,
                const rg::RoadGeometry::Ptr roadGeometry);

  static void ConvertLaneSection(const Road &road,
               const LaneSection& lane_section,
               const PlanView& planview, std::vector<LaneInternal>* lanes,
               const SectionLaneDivLines& divLine,
               const glm::dvec3& origin,
               const std::vector<LaneSection*>& laneSections);
  static void SetCenterCurve(double s, double e,
                   LaneInternal* lane_internal,
                   const rg::LaneDivRefLine& refLine,
                   const glm::dvec3& origin,
                   bool is_virtual_boundary);
  static void SetCenterAndBorderCurve(
                        double s, double e,
                        LaneInternal* lane_internal,                        
                        const rg::LaneDivRefLine& refLine,
                        const glm::dvec3& origin,
                        bool is_virtual_boundary,
                        const rg::LaneDivRefLine* preRefLine, bool isLeftLane);
  static void SetBorderType(const Lane& lane, const Lane* left_lane, LaneInternal* lane_internal, int index = -1);
  static void SetLaneBoundaryType(PbLaneBoundary* lane_boundary, const LaneRoadMark& roadMark);
  static void SetNeighbor(const std::vector<Lane*>& lanes, const Lane& lane, 
            LaneInternal* lane_internal);
  static void SetSampleAssociates(const Lane& lane, LaneInternal* lane_internal);
  static void SetRoadSampleAssociates(const std::vector<Lane*>& lanes,
                                      const Lane& lane, LaneInternal* lane_internal);

  static void ConvertLane(const Road &road, const Lane& lane, LaneInternal* lane_internal, bool lastSection, double end);
  // set predecessor and successor for lane
  static void SetLaneLink(const Lane& lane, LaneInternal* lane_internal, bool is_left);

  static void ConvertSectionBoundary(
               const LaneSection& lane_section, RoadSectionInternal& section_internal);
  static void FillBoundary(LaneInternal& lane_internal,
                                        PbBoundaryPolygon* boundary,
                                        bool is_left);
  //static double CalculateLaneWidth(const LaneWidth& laneWidth, double ds);

  // FIXME: Not sure these functions are needed or not
  static void SetSampleAssociatesForLeftLane(const Lane& lane, LaneInternal* lane_internal);
  static void  SetRoadSampleAssociatesForLeftLane(const std::vector<Lane*>& lanes,
                                      const Lane& lane, LaneInternal* lane_internal);
  static void SortPointCCW(const std::vector<apollo::common::PointENU>& boundary_points, 
                  std::vector<apollo::common::PointENU>& sorted_points);

  static bool reverseXAxis;
};

}  // namespace adapter
}  // namespace hdmap
}  // namespace apollo

#endif